﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using System.Collections.Generic;

using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using ARogueBeta.Helpers;
using CommonBehaviors.Actions;



namespace ARogueBeta
{
    class AltecRogue : CombatRoutine
    {
        public override string Name { get { return "[BETA] Altec's Rogue's Combat Routine. "; } }
        public override WoWClass Class { get { return WoWClass.Rogue; } }
        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        public override void Initialize()
        {
            Logging.Write("Hello, " + Me.Name + ",");
            Logging.Write("welcome to my BETA Selector CR!");
            Logging.Write("This is under Heavy Construction!");
        }
        public override bool WantButton
        {

            get { return true; }
        }
        public override void OnButtonPress()
        {
            var gui = new ARForm();
            gui.ShowDialog();
        }
        public override Composite CombatBehavior { get { return MainRotation(); } }
        public override Composite RestBehavior { get { return Resting(); } }
        public override Composite PullBehavior { get { return MainRotation(); } }

        #region Checks
        public bool ValidUnit(WoWUnit u)
        {
            if (u == null || !u.IsValid || !u.Attackable || !u.IsAlive || !u.CanSelect ||
                u.IsCritter && (u.CurrentTarget == null || u.CurrentTarget != null && u.CurrentTarget != Me) ||
                u.IsNonCombatPet || Blacklist.Contains(u.Guid, BlacklistFlags.Combat))
            {
                return false;
            }
            return true;
        }
        public bool IsEnemy(WoWUnit target)
        {
            if (target == null)
            {
                return false;
            }

            if (!target.IsFriendly && target.IsWithinMeleeRange)
            {
                return true;
            }
            return false;
        }
        public static string NoGCDSpells = "[Adrenaline Rush] [Blade Flurry] [Evasion] [Cloak of Shadows] [Sprint] [Shadow Blades] [Shadow Step] [Vanish] [Deadly Poison] [Wound Poison] [Crippling Poison] [Mind-numbing Poison] [Leeching Poison] [Paralytic Poison]";
        #region CastSpell

        public DateTime HoldRotationWhileFlying = DateTime.Now;
        public string LastCastSpell = "";
        public WoWUnit LastCastUnit;
        public WoWUnit LastCastUnitSoothingMist = Me;
        public DateTime LastCastTime = DateTime.Now;

        public void CastSpell(string spellName, WoWUnit u)
        {
            uint iCE;
            int iCP;
            if (u == null || !u.IsValid) { return; }
            if (SpellManager.CanCast(spellName, u)) { iCE = Me.CurrentEnergy; iCP = CP(); SpellManager.Cast(spellName, u); StyxWoW.SleepForLagDuration(); StyxWoW.SleepForLagDuration(); }
            else { return; }

            //Prevent spamming
            if (LastCastUnit != u || spellName != LastCastSpell || LastCastTime + TimeSpan.FromMilliseconds(500) < DateTime.Now)
            {
                if (AttackSpells.Contains(spellName))
                {
                    Logging.Write(Colors.Orange, "{0} - Energy: {1} - CP: {2} - {3} y - {4}", DateTime.Now.ToString("mm:ss:fff"), iCE, iCP, Math.Round(u.Distance), spellName);
                }
                else if (DefendSpells.Contains(spellName))
                {
                    Logging.Write(Colors.GreenYellow, "{0} - Energy: {1} - CP: {2} - {3} y - {4}", DateTime.Now.ToString("mm:ss:fff"), iCE, iCP, Math.Round(u.Distance), spellName);
                }
                else if (SpecialSpells.Contains(spellName))
                {
                    Logging.Write(Colors.OrangeRed, "{0} - Energy: {1} - CP: {2} - {3} y - {4}", DateTime.Now.ToString("mm:ss:fff"), iCE, iCP, Math.Round(u.Distance), spellName);
                }
                else
                {
                    Logging.Write(Colors.Yellow, "{0} - Energy: {1} - CP: {2} - {3} y - {4}", DateTime.Now.ToString("mm:ss:fff"), iCE, iCP, Math.Round(u.Distance), spellName);
                }
            }

            LastCastTime = DateTime.Now;
            LastCastSpell = spellName;
            LastCastUnit = u;

            if (!NoGCDSpells.Contains(spellName))
            {
                UpdateGCD();
            }
        }

        #endregion
        #region GCD

        public DateTime GCDReady;
        public double MyLatency = StyxWoW.WoWClient.Latency;

        public void UpdateGCD()
        {
            GCDReady = DateTime.Now + SpellManager.Spells["Slice and Dice"].CooldownTimeLeft;
        }

        public bool GCDL()
        {
            return DateTime.Now + TimeSpan.FromMilliseconds(MyLatency) <= GCDReady;
        }

        #endregion
        #region SpellType

        private static readonly HashSet<string> AttackSpells = new HashSet<string>
                                                                   {
                                                                       "Ambush",
                                                                       "Garrote",
                                                                       "Cheap Shot",
                                                                       "Sinister Strike",
                                                                       "Revealing Strike",
                                                                       "Fan of Knives",
                                                                       "Mutilate",
                                                                       "Dispatch",
                                                                       "Backstab",
                                                                       "Hemorrhage",
                                                                   };

        private static readonly HashSet<string> DefendSpells = new HashSet<string>
                                                                   {
                                                                       "Evasion",
                                                                       "Cloak of Shadows",
                                                                       "Vanish",
                                                                       "Combat Readiness",
                                                                       "Smoke Bomb",
                                                                       "Vanish",
                                                                       "Kick",
                                                                       "Recuperate",
                                                                   };

        private static readonly HashSet<string> SpecialSpells = new HashSet<string>
                                                                    {
                                                                        "Killing Spree",
                                                                        "Adrenaline Rush",
                                                                        "Shadow Blades",
                                                                        "Shadow Step",
                                                                        "Preperation",
                                                                        "Premeditation",
                                                                        "Shuriken Toss",
                                                                        "Burst of Speed",
                                                                        "Expose Armor",
                                                                        "Shiv",
                                                                        "Vendetta",
                                                                        "Rocket Barrage",
                                                                        "Shadow Dance",
                                                                        "Premeditation",
                                                                    };
        #endregion
        #region Recup / Slice and Dice
        public int Recup()
        {
            int RCP1 = 6;
            int RCP2 = 12;
            int RCP3 = 18;
            int RCP4 = 24;
            int RCP5 = 30;
            if (Me.ComboPoints == 0 || Me.RawComboPoints == 0)
                return 0;
            if (Me.ComboPoints == 1 || Me.RawComboPoints == 1)
                return RCP1;
            if (Me.ComboPoints == 2 || Me.RawComboPoints == 2)
                return RCP2;
            if (Me.ComboPoints == 3 || Me.RawComboPoints == 3)
                return RCP3;
            if (Me.ComboPoints == 4 || Me.RawComboPoints == 4)
                return RCP4;
            else return RCP5;
        }
        public int Slice()
        {
            int SCP1 = 12;
            int SCP2 = 18;
            int SCP3 = 24;
            int SCP4 = 30;
            int SCP5 = 36;
            if (Me.ComboPoints == 0 || Me.RawComboPoints == 0)
                return 0;
            if (Me.ComboPoints == 1 || Me.RawComboPoints == 1)
                return SCP1;
            if (Me.ComboPoints == 2 || Me.RawComboPoints == 2)
                return SCP2;
            if (Me.ComboPoints == 3 || Me.RawComboPoints == 3)
                return SCP3;
            if (Me.ComboPoints == 4 || Me.RawComboPoints == 4)
                return SCP4;
            else return SCP5;
        }
        #endregion
        #region Target Boss
        private bool IsTargetBoss()
        {
            if (ValidUnit(Me.CurrentTarget) && Me.CurrentTarget.IsBoss) 
            { 
                return true;
            } 
            else 
            { 
                return false; 
            } 
        }
        #endregion
        #region ComboPoints
        private int CP()
        {
            if (SpellManager.HasSpell("Anticipation")) return (Me.ComboPoints + Anticipation());
            else return (Me.ComboPoints);
        }
        private int Anticipation()
        {
            if (Me.HasAura("Anticipation", 1))
                return 1;
            if (Me.HasAura("Anticipation", 2))
                return 2;
            if (Me.HasAura("Anticipation", 3))
                return 3;
            if (Me.HasAura("Anticipation", 4))
                return 4;
            if (Me.HasAura("Anticipation", 5))
                return 5;
            else return 0;
        }
        #endregion
        #region AddCount
        private int addCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && Me.CurrentTarget != null
                    && u.Guid != Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.Location.Distance(Me.Location) <= 8
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }
        #endregion
        #region Blade Flurry AddCount
        private int BFaddCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && Me.CurrentTarget != null
                    && u.Guid != Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.IsWithinMeleeRange
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }
        #endregion
        #region Movement
        public static void MoveBehind(WoWUnit Unit)
        {

            WoWPoint BehindLocation = WoWMathHelper.CalculatePointBehind(Unit.Location, Unit.Rotation, 3f);
            Navigator.MoveTo(BehindLocation);
        }
        #endregion
        #endregion

        #region Rest
        public Composite Resting()
        {
            return new PrioritySelector(
                new Decorator(ret => Me.IsDead || Me.IsGhost || Me.IsCasting || Me.IsChanneling, new ActionAlwaysSucceed()),
                new Decorator(ret => !Me.Mounted && SpellManager.HasSpell("Stealth") && ARSettings.Instance.AlwaysStealth && !Me.HasAura("Stealth") && !Me.IsCasting && !Me.IsChanneling, new Action(delegate { CastSpell("Stealth", Me); return RunStatus.Failure; })),
                new Decorator(ret => !Me.Mounted && SpellManager.HasSpell(ARSettings.Instance.MHPoison) && (!Me.HasAura(ARSettings.Instance.MHPoison) || Me.GetAuraTimeLeft(ARSettings.Instance.MHPoison, true).TotalMinutes < ARSettings.Instance.MHPT), new Action(delegate { CastSpell(ARSettings.Instance.MHPoison, Me); StyxWoW.SleepForLagDuration(); StyxWoW.SleepForLagDuration(); return RunStatus.Failure; })),
                new Decorator(ret => !Me.Mounted && SpellManager.HasSpell(ARSettings.Instance.OHPoison) && (!Me.HasAura(ARSettings.Instance.OHPoison) || Me.GetAuraTimeLeft(ARSettings.Instance.OHPoison, true).TotalMinutes < ARSettings.Instance.OHPT), new Action(delegate { CastSpell(ARSettings.Instance.OHPoison, Me); StyxWoW.SleepForLagDuration(); StyxWoW.SleepForLagDuration(); return RunStatus.Failure; })),
                //Always using CP after Combat -- Slice and Dice
                new Decorator(ret => !Me.Mounted && SpellManager.HasSpell("Slice and Dice") && ARSettings.Instance.SpendCP && (!Me.HasAura("Slice and Dice") || Me.GetAuraTimeLeft("Slice and Dice", true).TotalMilliseconds + 1 < Slice()), new Action(delegate { CastSpell("Slice and Dice", Me); return RunStatus.Failure; })),
                //Always using CP after Combat -- Recup
                new Decorator(ret => !Me.Mounted && SpellManager.HasSpell("Recuperate") && ARSettings.Instance.SpendCP && Me.HasAura("Slice and Dice") && (!Me.HasAura("Recuperate") || Me.GetAuraTimeLeft("Recuperate", true).TotalMilliseconds + 1 < Recup()), new Action(delegate { CastSpell("Recuperate", Me); return RunStatus.Failure; })),
                //Food Detection
                new Decorator(ret => Me.HealthPercent <= 65 && (!Me.GroupInfo.IsInParty || !Me.GroupInfo.IsInRaid), new Action(delegate
                {
                    while (((Me.HasAura("Food") && Me.HealthPercent != 100) || (!Me.HasAura("Food") && Me.HealthPercent <= 90) || Me.HealthPercent <= 65) && Me.IsAlive)
                    {
                        if (!Me.Mounted && Me.HealthPercent <= 65 && Me.IsAlive && !Me.HasAura("Food") && (Styx.CommonBot.Inventory.Consumable.GetBestFood(false) != null)) { Styx.CommonBot.Rest.FeedImmediate(); }
                        if (!Me.Mounted && Me.HealthPercent <= 65 && Me.IsAlive && (Styx.CommonBot.Inventory.Consumable.GetBestFood(false) == null)) { Logging.Write("AFK Stealth while we wait for our HP to regen."); }
                        if (!Me.Mounted && !Me.HasAura("Stealth")) { CastSpell("Stealth", Me); }
                    }
                    return RunStatus.Failure;}))
                );
        }
        #endregion
        
        #region Combat
        public Composite MainRotation()
        {
            return new PrioritySelector(
                new Decorator(ret => Me.IsDead || Me.IsGhost || Me.IsCasting || Me.IsChanneling, new ActionAlwaysSucceed()),
                new Decorator(ret => (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && (Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid) && Me.CurrentTarget != null && !Me.CurrentTarget.Combat, new ActionAlwaysSucceed()),
                //Movement
                new Decorator(ret => ARSettings.Instance.FaceTarget && ValidUnit(Me.CurrentTarget) && !Me.IsSafelyFacing(Me.CurrentTarget, 70f) && Me.CurrentTarget.InLineOfSight && !Me.HasAura("Killing Spree"), new Action(delegate { Me.CurrentTarget.Face(); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.Movement && SpellManager.HasSpell("Shadowstep") && ARSettings.Instance.ShadowStep && ValidUnit(Me.CurrentTarget) && Me.CurrentTarget.Distance > 10 && Me.CurrentTarget.InLineOfSpellSight && !Me.HasAura("Killing Spree"), new Action(delegate { CastSpell("Shadowstep", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.Movement && SpellManager.HasSpell("Rocket Jump") && Me.IsSafelyFacing(Me.CurrentTarget, 20f) && ValidUnit(Me.CurrentTarget) && Me.CurrentTarget.Distance > 15 && Me.CurrentTarget.InLineOfSpellSight && !Me.HasAura("Killing Spree"), new Action(delegate { CastSpell("Rocket Jump", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.Movement && SpellManager.HasSpell("Sprint") && (SpellManager.HasSpell("Shadow Step") && !SpellManager.CanCast("Shadow Step") || !SpellManager.HasSpell("Shadow Step")) && ValidUnit(Me.CurrentTarget) && !Me.CurrentTarget.IsWithinMeleeRange && Me.CurrentTarget.InLineOfSpellSight && !Me.HasAura("Killing Spree"), new Action(delegate { CastSpell("Sprint", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.Movement && Me.CurrentTarget.Distance > 2.5 && !Me.CurrentTarget.IsWithinMeleeRange && !Me.HasAura("Killing Spree"), new Action(delegate { MoveBehind(Me.CurrentTarget); Logging.Write("Moving to the target"); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.Movement && ValidUnit(Me.CurrentTarget) && (Me.CurrentTarget.Distance > 2.5 && Me.CurrentTarget.IsWithinMeleeRange) && !Me.HasAura("Killing Spree"), new Action(delegate { Navigator.PlayerMover.MoveStop(); return RunStatus.Failure; })),
                //End of Movement
                //Pick Pocket -- 5m default seems buggy atm
                new Decorator(ret => Me.HasAura("Stealth") && ValidUnit(Me.CurrentTarget) && Me.CurrentTarget.IsHumanoid && Me.CurrentTarget.Distance <= 5, new Action(delegate { CastSpell("Pick Pocket", Me.CurrentTarget); return RunStatus.Failure; })),
                //Target is interuptable
                new Decorator(ret => SpellManager.HasSpell("Kick") && ARSettings.Instance.Kick && !Me.IsStealthed && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (Me.CurrentTarget.IsCasting || Me.CurrentTarget.IsChanneling) && Me.CurrentTarget.CanInterruptCurrentSpellCast, new Action(delegate { CastSpell("Kick", Me.CurrentTarget); return RunStatus.Failure; })),
                //Energy Regen Mechanic -- Slice and Dice
                new Decorator(ret => SpellManager.HasSpell("Slice and Dice") && CP() > 0 && (!Me.HasAura("Slice and Dice") || Me.GetAuraTimeLeft("Slice and Dice", true).TotalSeconds < 3), new Action(delegate { CastSpell("Slice and Dice", Me); return RunStatus.Failure; })),
                //Energy Regen Mechanic -- Rupture
                new Decorator(ret => SpellManager.HasSpell("Rupture") && !Me.IsStealthed && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && ((ARSettings.Instance.Spec == "Combat" && ARSettings.Instance.Rupture && !Me.HasAura("Blade Flurry") && CP() > 4) || ARSettings.Instance.Spec != "Combat" && CP() > 0) && (!Me.CurrentTarget.HasMyAura("Rupture") || Me.CurrentTarget.GetAuraTimeLeft("Rupture", true).TotalSeconds < 5), new Action(delegate { CastSpell("Rupture", Me.CurrentTarget); return RunStatus.Failure; })),
                //Tricks of the Trade -- Target's Target
                new Decorator(ret => SpellManager.HasSpell("Tricks of the Trade") && (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && (Me.IsStealthed || (Me.FocusedUnit != null && !Me.FocusedUnit.IsAlive && Me.FocusedUnit.IsFriendly)) && Me.CurrentTarget.CurrentTarget.IsAlive && Me.CurrentTarget.CurrentTarget.IsFriendly, new Action(delegate { CastSpell("Tricks of the Trade", Me.CurrentTarget.CurrentTarget); return RunStatus.Failure; })),
                //Tricks of the Trade -- Focus Target
                new Decorator(ret => SpellManager.HasSpell("Tricks of the Trade") && (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && !Me.IsStealthed && Me.FocusedUnit != null && Me.FocusedUnit.IsAlive && Me.FocusedUnit.IsFriendly, new Action(delegate { CastSpell("Tricks of the Trade", Me.FocusedUnit); return RunStatus.Failure; })),
                //Blade Flurry
                new Decorator(ret => SpellManager.HasSpell("Blade Flurry") && ARSettings.Instance.BladeFlurry && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.HasAura("Killing Spree") && BFaddCount() >= 2 && !Me.HasAura("Blade Flurry"), new Action(delegate { CastSpell("Blade Flurry", Me); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Blade Flurry") && ARSettings.Instance.BladeFlurry && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.HasAura("Killing Spree") && BFaddCount() < 2 && Me.HasAura("Blade Flurry"), new Action(delegate { Me.CancelAura("Blade Flurry"); return RunStatus.Failure; })),
                //Self Heals
                //Recup
                new Decorator(ret => SpellManager.HasSpell("Recuperate") && ARSettings.Instance.Recuperate && Me.ComboPoints > 0 && Me.HealthPercent < ARSettings.Instance.RHP && !Me.HasAura("Recuperate"), new Action(delegate{CastSpell("Recuperate", Me);return RunStatus.Failure;})),
                //Shiv
                new Decorator(ret => SpellManager.HasSpell("Shiv") && ARSettings.Instance.AShiv && !Me.IsStealthed && ARSettings.Instance.OHPoison == "Cripple Poison" && Me.HasAura(ARSettings.Instance.OHPoison) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.CurrentTarget.IsMoving && !Me.CurrentTarget.HasAura("Debilitating poison"), new Action(delegate { CastSpell("Shiv", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Shiv") && ARSettings.Instance.AShiv && !Me.IsStealthed && ARSettings.Instance.OHPoison == "Mind-numbing Poison" && Me.HasAura(ARSettings.Instance.OHPoison) && !SpellManager.CanCast("Kick") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.CurrentTarget.HasAura("Mind Paralysis"), new Action(delegate { CastSpell("Shiv", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Shiv") && ARSettings.Instance.AShiv && !Me.IsStealthed && ARSettings.Instance.OHPoison == "Leeching Poison" && Me.HasAura(ARSettings.Instance.OHPoison) && Me.HealthPercent < ARSettings.Instance.RHP, new Action(delegate { CastSpell("Shiv", Me.CurrentTarget); return RunStatus.Failure; })),

                #region Boss CD's / Always Use CD's
                //Boss CDs / always use CDs
                //Expose Armor
                new Decorator(ret => SpellManager.HasSpell("Expose Armor") && ARSettings.Instance.ExposeArmor && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && Me.CurrentTarget.HasMyAura("Weakened Armor") && Me.CurrentTarget.GetAuraByName("Weakened Armor").StackCount < 3, new Action(delegate { CastSpell("Expose Armor", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Expose Armor") && ARSettings.Instance.ExposeArmor && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && (!Me.CurrentTarget.HasAura("Weakened Armor") || Me.CurrentTarget.GetAuraTimeLeft("Weakened Armor", false).TotalSeconds < 3), new Action(delegate { CastSpell("Expose Armor", Me.CurrentTarget); return RunStatus.Failure; })),
                //Shadow Blades
                new Decorator(ret => SpellManager.HasSpell("Shadow Blades") && ARSettings.Instance.ShadowBlades && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.HasAura("Killing Spree") && !Me.IsStealthed, new Action(delegate { CastSpell("Shadow Blades", Me); return RunStatus.Failure; })),
                //Vanish
                new Decorator(ret => SpellManager.HasSpell("Vanish") && ARSettings.Instance.Vanish && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && ((ARSettings.Instance.Spec == "Sublety" && !Me.CurrentTarget.HasMyAura("Find Weakness")) || ARSettings.Instance.Spec != "Sublety"), new Action(delegate {CastSpell("Vanish", Me); return RunStatus.Failure;})),
                //Assassination - Vendetta
                new Decorator(ret => SpellManager.HasSpell("Vendetta") && ARSettings.Instance.Vendetta && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget), new Action(delegate { CastSpell("Vendetta", Me.CurrentTarget); return RunStatus.Failure; })),
                //Combat - Adrenaline Rush
                new Decorator(ret => SpellManager.HasSpell("Adrenaline Rush") && ARSettings.Instance.AdrenalineRush && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.HasAura("Killing Spree") && !Me.IsStealthed, new Action(delegate { CastSpell("Adrenaline Rush", Me); return RunStatus.Failure; })),
                //Combat - Killing Spree
                new Decorator(ret => SpellManager.HasSpell("Killing Spree") && ARSettings.Instance.KillingSpree && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.IsStealthed && Me.CurrentEnergy < 40 && !Me.HasAura("Adrenaline Rush") && !Me.HasAura("Shadow Blades"), new Action(delegate {CastSpell("Killing Spree", Me); return RunStatus.Failure;})),
                //Sublety - Premeditation
                new Decorator(ret => SpellManager.HasSpell("Premeditation") && ARSettings.Instance.Premeditation && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && (Me.IsStealthed || Me.HasAura("Shadow Dance")), new Action(delegate { CastSpell("Premeditation", Me.CurrentTarget); return RunStatus.Failure; })),
                //Sublety - Shadow Dance
                // ***** needs behind check *****
                new Decorator(ret => SpellManager.HasSpell("Shadow Dance") && ARSettings.Instance.ShadowDance && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && !Me.CurrentTarget.HasMyAura("Find Weakness"), new Action(delegate { CastSpell("Shadow Dance", Me); return RunStatus.Failure; })),
                //Talent - Preparation 
                // ***** need talent checker *****
                new Decorator(ret => SpellManager.HasSpell("Preparation") && ARSettings.Instance.Preparation && (IsTargetBoss() || ARSettings.Instance.UseCDs) && !SpellManager.CanCast("Vanish") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed, new Action(delegate { CastSpell("Preparation", Me); return RunStatus.Failure; })),
                //Racials
                //Arcane Torrent
                new Decorator(ret => SpellManager.HasSpell("Arcane Torrent") && ARSettings.Instance.ArcaneTorrent && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && (Me.CurrentEnergy < 85 || ((Me.CurrentTarget.IsCasting || Me.CurrentTarget.IsChanneling) && Me.CurrentTarget.CanInterruptCurrentSpellCast && Me.CurrentTarget.Distance <= 8)), new Action(delegate { CastSpell("Arcane Torrent", Me.CurrentTarget); return RunStatus.Failure; })),
                //Berserking
                new Decorator(ret => SpellManager.HasSpell("Berserking") && ARSettings.Instance.Berserking && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed, new Action(delegate { CastSpell("Berserking", Me); return RunStatus.Failure; })),
                //Blood Fury
                new Decorator(ret => SpellManager.HasSpell("Blood Fury") && ARSettings.Instance.BloodFury && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed, new Action(delegate { CastSpell("Blood Fury", Me); return RunStatus.Failure; })),
                //Rocket Barrage
                new Decorator(ret => SpellManager.HasSpell("Rocket Barrage") && ARSettings.Instance.RocketBarrage && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && Me.CurrentTarget.Distance <= 30 && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed, new Action(delegate { CastSpell("Rocket Barrage", Me.CurrentTarget); return RunStatus.Failure; })),
                //Engy Gloves
                new Decorator(ret => ARSettings.Instance.UseEngineeringGloves && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && Me.Inventory.Equipped.Hands.Usable && Me.Inventory.Equipped.Hands.Cooldown == 0, new Action(delegate { Me.Inventory.Equipped.Hands.Use(); return RunStatus.Failure; })),
                //Trinkets
                new Decorator(ret => ARSettings.Instance.UseTrinkets && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && Me.Inventory.Equipped.Trinket1.Usable && Me.Inventory.Equipped.Trinket1.Cooldown == 0, new Action(delegate { Me.Inventory.Equipped.Trinket1.Use(); return RunStatus.Failure; })),
                new Decorator(ret => ARSettings.Instance.UseTrinkets && (IsTargetBoss() || ARSettings.Instance.UseCDs) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.IsFacing(Me.CurrentTarget) && !Me.IsStealthed && Me.Inventory.Equipped.Trinket2.Usable && Me.Inventory.Equipped.Trinket2.Cooldown == 0, new Action(delegate { Me.Inventory.Equipped.Trinket2.Use(); return RunStatus.Failure; })),
                #endregion

                //AoE
                new Decorator(ret => SpellManager.HasSpell("Fan of Knives") && ARSettings.Instance.AOE && addCount() >= ARSettings.Instance.AoeAmount, AoERotation()),
                //Assassination
                new Decorator(ret => SpellManager.HasSpell("Mutilate") && (!SpellManager.HasSpell("Fan of Knives") || !ARSettings.Instance.AOE || addCount() < ARSettings.Instance.AoeAmount), AssassinationRotation()),
                //Combat Spec
                new Decorator(ret => !SpellManager.HasSpell("Mutilate") && !SpellManager.HasSpell("Backstab") && (!SpellManager.HasSpell("Fan of Knives") || !ARSettings.Instance.AOE || addCount() < ARSettings.Instance.AoeAmount), CombatRotation()),
                //Sublety Spec
                new Decorator(ret => SpellManager.HasSpell("Backstab") && (SpellManager.HasSpell("Fan of Knives") || !ARSettings.Instance.AOE || addCount() < ARSettings.Instance.AoeAmount), SubletyRotation())
            );
        }

        //AoE
        public Composite AoERotation()
        {
            return new PrioritySelector(
                new Decorator(ret => SpellManager.HasSpell("Crimson Tempest") && CP() > 4 && !Me.IsStealthed && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.CurrentTarget.HasMyAura("Crimson Tempest"), new Action(delegate { CastSpell("Crimson Tempest", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => CP() > 4 && !Me.IsStealthed && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (!SpellManager.HasSpell("Crimson Tempest") || Me.CurrentTarget.HasMyAura("Crimson Tempest")), new Action(delegate { CastSpell("Eviscerate", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => (!SpellManager.HasSpell("Anticipation") && CP() < 5|| SpellManager.HasSpell("Anticipation") && CP() < 9) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget), new Action(delegate { CastSpell("Fan of Knives", Me.CurrentTarget); return RunStatus.Failure; }))
                    );
        }

        //Assassin Spec
        public Composite AssassinationRotation() 
        {  
            return new PrioritySelector(
                new Decorator(ret => SpellManager.HasSpell("Envenom") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && ((CP() > 0 && Me.GetAuraTimeLeft("Slice and Dice", true).TotalSeconds < 5) || (CP() > 4 && !Me.HasAura("Envenom") && Me.CurrentTarget.GetAuraTimeLeft("Rupture", true).TotalSeconds > 5) || (CP() > 7)), new Action(delegate { CastSpell("Envenom", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Dispatch") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.IsStealthed && (!SpellManager.HasSpell("Anticipation") && CP() < 5 || SpellManager.HasSpell("Anticipation") && CP() < 8) && (Me.HasAura("Blindside") || Me.CurrentTarget.HealthPercent < 35), new Action(delegate { CastSpell("Dispatch", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Mutilate") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (!SpellManager.HasSpell("Anticipation") && CP() < 4 || SpellManager.HasSpell("Anticipation") && CP() < 7) && Me.CurrentTarget.HealthPercent >= 35, new Action(delegate { CastSpell("Mutilate", Me.CurrentTarget); return RunStatus.Failure; }))
                            
            );
        }

        //Combat Spec
        public Composite CombatRotation()
        {
            return new PrioritySelector(
                new Decorator(ret => SpellManager.HasSpell("Eviscerate") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && CP() > 4 && Me.CurrentTarget.HasMyAura("Revealing Strike") && !Me.IsStealthed, new Action(delegate { CastSpell("Eviscerate", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (!SpellManager.HasSpell("Anticipation") && CP() < 5 || SpellManager.HasSpell("Anticipation") && CP() < 8) && (!SpellManager.HasSpell("Revealing Strike") || Me.CurrentTarget.HasMyAura("Revealing Strike")), new Action(delegate { CastSpell("Sinister Strike", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Revealing Strike") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.CurrentTarget.HasMyAura("Revealing Strike"), new Action(delegate { CastSpell("Revealing Strike", Me.CurrentTarget); return RunStatus.Failure; }))
                    );
        }

        //Sublety Spec
        public Composite SubletyRotation()
            {
            return new PrioritySelector(
                new Decorator(ret => SpellManager.HasSpell("Eviscerate") && (Me.CurrentTarget.HasMyAura("Rupture") || Me.CurrentTarget.HasMyAura("Garrote") || Me.CurrentTarget.HasMyAura("Crimson Tempest")) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (CP() > 4 || SpellManager.HasSpell("Anticipation") && Me.HasAura("Shadow Dance") && CP() > 7) && !Me.IsStealthed, new Action(delegate { CastSpell("Eviscerate", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Garrote") && (Me.HasAura("Shadow Dance") || Me.HasAura("Stealth")) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && !Me.CurrentTarget.HasMyAura("Garrote"), new Action(delegate { CastSpell("Garrote", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Ambush") && (Me.HasAura("Shadow Dance") || Me.HasAura("Stealth")) && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && Me.CurrentTarget.HasMyAura("Garrote"), new Action(delegate {CastSpell("Ambush", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Backstab") && !Me.HasAura("Shadow Dance") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (!SpellManager.HasSpell("Anticipation") && CP() < 5 || SpellManager.HasSpell("Anticipation") && CP() < 9) && Me.CurrentTarget.HasMyAura("Hemorrhage") && Me.IsBehind(Me.CurrentTarget), new Action(delegate { CastSpell("Backstab", Me.CurrentTarget); return RunStatus.Failure; })),
                new Decorator(ret => SpellManager.HasSpell("Hemorrhage") && !Me.HasAura("Shadow Dance") && ValidUnit(Me.CurrentTarget) && IsEnemy(Me.CurrentTarget) && (!SpellManager.HasSpell("Anticipation") && CP() < 5 || SpellManager.HasSpell("Anticipation") && CP() < 9) && (!Me.IsBehind(Me.CurrentTarget) || !Me.CurrentTarget.HasMyAura("Hemorrhage")), new Action(delegate { CastSpell("Hemorrhage", Me.CurrentTarget); return RunStatus.Failure; }))
                    );
        }
        #endregion
    }
}
